#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <fstream>
#include <assert.h>
#include "panda.h"
#include "transfer_data_to_postgres.h"
#include "components/progress_indicator.h"
//#include "postgres_io_binary.h"
#define _MY_STL_MACROS 1
#include "components/stlhelper.h"
#include "components/pg_db_cursor.h"
#include "components/libpq++/libpq++.h"


using std::ostream;
using std::less;
using std::vector;
using std::deque;
using std::string;
using std::sort;



//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
//		synchronize_sequence_dependent_tables

//			retrieve a list of tables dependent on the sequences table

//			remove all orphaned entries linked to obsolete sequences

//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
bool synchronize_sequence_dependent_tables(	t_pg_cursor&	 	pg_db,
											deque<t_pi>&		seq_pi_all,
											ostream&			VERBOSE,
											ostream&			CERR)
{
	assert(stlhelper::is_sorted(beg_to_end(seq_pi_all), less<t_pi>()));

	// select list of tables from postgreSQL
	string SQL_command = "Select * from sequences_linked_tables";
	if( !pg_db.ExecTuplesOk(SQL_command.c_str()))
	{
		CERR
		<< "ERROR!! Failed to obtain a list of tables linked to "
		   "the sequences table\n\n"
		<< SQL_command << "\n"
		<< pg_db.ErrorMessage();
		return false;
	}

	// get list from pgSQL
	vector<string> dependent_tables;
	int rows = pg_db.Tuples();
	for (int i = 0; i < rows; ++i)
		dependent_tables.push_back(pg_db.GetValue(i, 0));

	// make sure list of table contains no duplicates
	dependent_tables.push_back("new_sequences");
	sort(beg_to_end(dependent_tables));
	remove_duplicates(dependent_tables);


	deque<t_pi> dependent_pi_obsolete;
	
	// iterate through tables, removing orphans
	for (unsigned i = 0; i < dependent_tables.size(); ++i)
	{
		VERBOSE << "\tfrom " << dependent_tables[i] << ":\n";
		deque<t_pi> dependent_pi_all;
		if (!pg_import_PIs_from_table(pg_db, dependent_tables[i], dependent_pi_all, 0,
										VERBOSE, CERR))
			return false;
		sort(beg_to_end(dependent_pi_all));
		remove_duplicates(dependent_pi_all);
		
		dependent_pi_obsolete.clear();
		set_difference(	beg_to_end(dependent_pi_all),
						beg_to_end(seq_pi_all),
						back_inserter(dependent_pi_obsolete));
		if (!pg_remove_PIs_from_table(	pg_db,
										dependent_tables[i],
										dependent_pi_obsolete,
                                        VERBOSE,
										CERR))
			return false;
	}
	
	return true;
}






